console.log('fur--promise')
let PENDING = 'PENDING'
let RESOLVED = 'RESOLVED'
let REJECTED = 'REJECTED'
//规定：这里写法兼容所有promise，需要可以融合别的库的promise
const resolvePromise = (promise2, x, resolve, reject) => {
    // 判断x的值
    if (promise2 === x) {
        // 自我等待，永久等待
        return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    // 判断数据类型 typeof constructor instanceof toString
    if ((typeof x === 'object' && x !== null )|| typeof x === 'function') {
        let called; //内部测试的时候，会成功失败都调
        try {
            let then = x.then //去then属性报错，有可能通过defineProperty定义的
            // 当有then方法，我就认为是一个promise
            if (typeof then === 'function') {
                //可以防止二次取值报错，不用再次去取then
                then.call(x, y => {
                    //y可能还是promise，进行递归，知道是普通值
                    if (called) return
                    called = true
                    resolvePromise(promise2, y, resolve, reject) //采用promise成功结果向下传递
                }, r => {
                    if (called) return
                    called = true
                    reject(r) //采用promise失败结果向下传递
                })

            } else {
                // x是普通值
                resolve(x)
            }
        } catch (e) {
            // promise失败了，有可能还能调成功（别人不规范的封装），需要忽略，加层屏蔽
            if (called) return
            called = true
            reject(e)
        }
    } else {
        //x是普通值，直接让promise成功即可
        resolve(x)
    }

}
class Promise {
    // 1.看这个属性能否在原型上使用，then
    // 2.看属性是否公用，status不公用，放在构造函数内
    constructor(executor) {
        this.status = PENDING
        this.value = undefined
        this.reason = undefined
        this.onResolvedCallbacks = [] //Promise resolve时的回调函数集
        this.onRejectedCallbacks = [] // Promise reject时的回调函数集
        // resolve和reject是实例方法
        let resolve = (value) => {
            if (this.status === PENDING) {
                this.value = value
                this.status = RESOLVED
                // 发布
                this.onResolvedCallbacks.forEach(fn => fn())
            }
        }
        let reject = (reason) => {
            if (this.status === PENDING) {
                this.reason = reason
                this.status = REJECTED
                this.onRejectedCallbacks.forEach(fn => fn())
            }
        }
        // 此try catch只能捕获同步异常
        // promise内的默认立即执行
        try {
            executor(resolve, reject) //立即执行器
        } catch (e) {
            reject(e)
        }
    }
    //then是原型上的方法
    then(onfulfilled, onrejected) {
        // then的链式调用,then方法是异步的
        // onFulfilled，onRejected是可选参数
        onfulfilled = typeof onfulfilled === 'function' ? onfulfilled : val=>val
        onrejected = typeof onrejected === 'function' ? onrejected : err=>{
            throw err
        }
        let promise2 = new Promise((resolve, reject) => {
            // 同步
            if (this.status === RESOLVED) {
                setTimeout(() => {
                    try {
                        let x = onfulfilled(this.value)
                        // x可能是普通值，也可能是promise
                        //判断x的值 =》 promise2的状态
                        //new完Promise才能拿到promise2，需要用异步
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                }, 0)
            }
            if (this.status === REJECTED) {
                setTimeout(() => {
                    try {
                        let x = onrejected(this.reason)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                }, 0)

            }
            //异步，订阅，还未有状态时，需要先存储回调函数集
            if (this.status === PENDING) {
                this.onResolvedCallbacks.push(() => { //AOP切片，方便后续有需要插入的内容
                    setTimeout(() => {
                        try {
                            let x = onfulfilled(this.value)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                })
                this.onRejectedCallbacks.push(() => { //AOP切片，方便后续有需要插入的内容
                    setTimeout(() => {
                        try {
                            let x = onrejected(this.reason)
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                })
            }
        })
        return promise2
    }
}
Promise.defer = Promise.deferred = function (){
    let dfd = {}
    dfd.promise = new Promise((resolve,reject)=>{
        dfd.resolve= resolve
        dfd.reject = reject
    })
    return dfd
}
//注意写法
module.exports = Promise